package com.gy.service.impl;

import com.github.benmanes.caffeine.cache.*;
import com.gy.service.*;
import com.gy.vo.summary.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.gy.entity.result.Papers;
import com.gy.entity.result.Patents;
import com.gy.entity.result.Certification;
import com.gy.entity.result.Other;
import com.gy.entity.result.CopyRight;
import com.gy.entity.result.ContinueEducationMaterial;
@Service
public class SummaryCacheService {
    private final LoadingCache<Long, List<CertificationVO>> certificationCache;
    private final LoadingCache<Long, List<ContinueEducationMaterialVO>> educationCache;
    private final LoadingCache<Long, List<CopyRightVO>> copyRightCache;
    private final LoadingCache<Long, List<OtherVO>> otherCache;

    private final LoadingCache<Long, List<PapersVO>> papersCache;
    private final LoadingCache<Long, List<PatentsVO>> patentsCache;


    @Autowired
    private CertificationService certificationService;

    @Autowired
    private ContinueEducationMaterialService continueEducationMaterialService;

    @Autowired
    private CopyRightService copyRightService;

    @Autowired
    private OtherService otherService;

    @Autowired
    private PapersService papersService;

    @Autowired
    private PatentsService patentsService;

    public SummaryCacheService() {
        // 适用于 refreshAfterWrite 的 LoadingCache
        this.certificationCache = buildLoadingCache(this::loadCertificationFromDB);
        this.educationCache = buildLoadingCache(this::loadEducationFromDB);
        this.copyRightCache = buildLoadingCache(this::loadCopyRightFromDB);
        this.otherCache = buildLoadingCache(this::loadOtherFromDB);
        this.papersCache = buildLoadingCache(this::loadPapersFromDB);
        this.patentsCache = buildLoadingCache(this::loadPatentsFromDB);
    }

    private <T> LoadingCache<Long, List<T>> buildLoadingCache(CacheLoader<Long, List<T>> loader) {
        return Caffeine.newBuilder()
                .maximumSize(1000) // 限制缓存条数，防止占用太多内存
                .expireAfterWrite(10, TimeUnit.MINUTES) // 10分钟后过期
                .refreshAfterWrite(5, TimeUnit.MINUTES) // 5分钟后自动后台刷新
                .build(loader);
    }

    public List<CertificationVO> getCertificationSummary(Long userId) {
        return certificationCache.get(userId);
    }

    public List<ContinueEducationMaterialVO> getEducationSummary(Long userId) {
        return educationCache.get(userId);
    }

    public List<CopyRightVO> getCopyRightsSummary(Long userId) {
        return copyRightCache.get(userId);
    }

    public List<OtherVO> getOtherSummary(Long userId) {
        return otherCache.get(userId);
    }

    public List<PapersVO> getPapersSummary(Long userId) {
        return papersCache.get(userId);
    }

    public List<PatentsVO> getPatentsSummary(Long userId) {
        return patentsCache.get(userId);
    }

    // 数据库查询方法
    private List<CertificationVO> loadCertificationFromDB(Long userId) {
        return certificationService.lambdaQuery()
                .eq(Certification::getUserId, userId)
                .select(
                        Certification::getTitle,
                        Certification::getObtainTime,
                        Certification::getCertificateType,
                        Certification::getCertificateNumber,
                        Certification::getIssuingInstitution
                ).list()
                .stream()
                .map(certification -> CertificationVO.builder()
                        .title(certification.getTitle())
                        .obtainTime(certification.getObtainTime())
                        .certificateType(certification.getCertificateType())
                        .certificateNumber(certification.getCertificateNumber())
                        .issuingInstitution(certification.getIssuingInstitution())
                        .build())
                .collect(Collectors.toList());

    }

    private List<ContinueEducationMaterialVO> loadEducationFromDB(Long userId) {
        return continueEducationMaterialService.lambdaQuery()
                .eq(ContinueEducationMaterial::getUserId, userId)
                .select(
                        ContinueEducationMaterial::getTitle,
                        ContinueEducationMaterial::getHours,
                        ContinueEducationMaterial::getScore,
                        ContinueEducationMaterial::getObtainTime,
                        ContinueEducationMaterial::getTrainingUnit
                ).list()
                .stream()
                .map(cem -> ContinueEducationMaterialVO.builder()
                        .title(cem.getTitle())
                        .hours(cem.getHours())
                        .score(cem.getScore())
                        .obtainTime(cem.getObtainTime())
                        .trainingUnit(cem.getTrainingUnit())
                        .build())
                .collect(Collectors.toList());

    }

    private List<CopyRightVO> loadCopyRightFromDB(Long userId) {
        return copyRightService.lambdaQuery()
                .eq(CopyRight::getUserId, userId)
                .select(
                        CopyRight::getTitle,
                        CopyRight::getCertificateNo,
                        CopyRight::getPuttime,
                        CopyRight::getCopyrightType,
                        CopyRight::getCopyrightOwner,
                        CopyRight::getAuthorRank,
                        CopyRight::getFinishTime,
                        CopyRight::getRegisterNo
                ).list()
                .stream()
                .map(copyRight -> CopyRightVO.builder()
                        .title(copyRight.getTitle())
                        .certificateNo(copyRight.getCertificateNo())
                        .puttime(copyRight.getPuttime())
                        .copyrightType(copyRight.getCopyrightType())
                        .copyrightOwner(copyRight.getCopyrightOwner())
                        .authorRank(copyRight.getAuthorRank())
                        .finishTime(copyRight.getFinishTime())
                        .registerNo(copyRight.getRegisterNo())
                        .build())
                .collect(Collectors.toList());

    }

    private List<OtherVO> loadOtherFromDB(Long userId) {
        return otherService.lambdaQuery()
                .eq(Other::getUserId, userId)
                .select(Other::getTitle, Other::getAuthorRank, Other::getObtainTime)
                .list()
                .stream()
                .map(other -> OtherVO.builder()
                        .title(other.getTitle())
                        .authorRank(other.getAuthorRank())
                        .obtainTime(other.getObtainTime())
                        .build())
                .collect(Collectors.toList());

    }



    private List<PapersVO> loadPapersFromDB(Long userId) {
        return papersService.lambdaQuery()
                .eq(Papers::getUserId, userId)
                .select(Papers::getTitle, Papers::getPaperType, Papers::getResearchField,
                        Papers::getAuthorRank, Papers::getCorrespondingAuthor, Papers::getJournalName,
                        Papers::getIndexing, Papers::getPublishDate, Papers::getDoi,
                        Papers::getCitationCount, Papers::getKeywords, Papers::getPageRange,
                        Papers::getImpactFactor, Papers::getVolumeNumber, Papers::getIssueNumber,
                        Papers::getIssn, Papers::getCnNumber, Papers::getAbstractContent)
                .list()
                .stream()
                .map(paper -> PapersVO.builder()
                        .title(paper.getTitle())
                        .paperType(paper.getPaperType())
                        .researchField(paper.getResearchField())
                        .authorRank(paper.getAuthorRank())
                        .correspondingAuthor(paper.getCorrespondingAuthor())
                        .journalName(paper.getJournalName())
                        .indexing(paper.getIndexing())
                        .publishDate(paper.getPublishDate())
                        .doi(paper.getDoi())
                        .citationCount(paper.getCitationCount())
                        .keywords(paper.getKeywords())
                        .pageRange(paper.getPageRange())
                        .impactFactor(paper.getImpactFactor())
                        .volumeNumber(paper.getVolumeNumber())
                        .issueNumber(paper.getIssueNumber())
                        .issn(paper.getIssn())
                        .cnNumber(paper.getCnNumber())
                        .abstractContent(paper.getAbstractContent())
                        .build())
                .collect(Collectors.toList());
    }

    private List<PatentsVO> loadPatentsFromDB(Long userId) {
        return patentsService.lambdaQuery()
                .eq(Patents::getUserId, userId)
                .select(Patents::getTitle, Patents::getPatentType, Patents::getPatentNumber,
                        Patents::getAuthorizationDate, Patents::getApplicationDate, Patents::getAuthorRank,
                        Patents::getApplicationNumber, Patents::getPatentStatus, Patents::getPatentOwner)
                .list()
                .stream()
                .map(patent -> PatentsVO.builder()
                        .title(patent.getTitle())
                        .patentType(patent.getPatentType())
                        .patentNumber(patent.getPatentNumber())
                        .authorizationDate(patent.getAuthorizationDate())
                        .applicationDate(patent.getApplicationDate())
                        .authorRank(patent.getAuthorRank())
                        .applicationNumber(patent.getApplicationNumber())
                        .patentStatus(patent.getPatentStatus())
                        .patentOwner(patent.getPatentOwner())
                        .build())
                .collect(Collectors.toList());
    }
}
